// 两个顶点索引组成一条直线
interface VP {
    i0: number
    i1: number
}

function containVP(lineIndicesPairs: VP[], i0: number, i1: number) {
    let item = lineIndicesPairs.find(item => {
        return (item.i0 == i0 && item.i1 == i1) || (item.i0 == i1 && item.i1 == i0);
    });
    return item != null;
}


export class Box3 {
    minx: number = Number.POSITIVE_INFINITY;
    maxx: number = Number.NEGATIVE_INFINITY;
    miny: number = Number.POSITIVE_INFINITY;
    maxy: number = Number.NEGATIVE_INFINITY;
    minz: number = Number.POSITIVE_INFINITY;
    maxz: number = Number.NEGATIVE_INFINITY;
}

export class VertexData {
    positions: Array<number>;
    normals: Array<number>;
    texCoords: Array<number>;
    indices: Array<number>;

    // wireframe indices array
    lineIndicesArray: Array<number>;

    // typedArray
    posBufferData: Float32Array;
    normalBufferData: Float32Array;
    texCoordBufferData: Float32Array;
    indiceBufferData: Uint16Array;
    lineIndicesBufferData: Uint16Array;

    //  boundingbox
    box:Box3;
    bbPosBufferData:Float32Array;
    bbIndiceBufferData:Uint16Array;

    // boundingsphere
    radius:number;

    constructor(info: {
        positions: number[],
        normals: number[],
        texCoords: number[],
        indices: number[],
    }) {
        this.positions = info.positions;
        this.normals = info.normals;
        this.texCoords = info.texCoords;
        this.indices = info.indices;

        // 获取所有的线段
        // 排除掉重复的
        let lineIndicesPairs: VP[] = [];
        let indices = this.indices;
        let facelen = indices.length / 3;
        for (let i = 0; i < facelen; ++i) {
            let i0 = indices[3 * i];
            let i1 = indices[3 * i + 1];
            let i2 = indices[3 * i + 2];
            if (!containVP(lineIndicesPairs, i0, i1)) {
                lineIndicesPairs.push({i0: i0, i1: i1});
            }
            if (!containVP(lineIndicesPairs, i1, i2)) {
                lineIndicesPairs.push({i0: i1, i1: i2});
            }
            if (!containVP(lineIndicesPairs, i2, i0)) {
                lineIndicesPairs.push({i0: i2, i1: i0});
            }
        }

        // 计算 wireframe 需要的 indices
        this.lineIndicesArray = [];
        lineIndicesPairs.forEach(item => {
            // @ts-ignore
            this.lineIndicesArray.push(item.i0, item.i1);
        });


        // 创造各种buffer
        this.posBufferData = new Float32Array(this.positions);
        this.normalBufferData = new Float32Array(this.normals);
        this.texCoordBufferData = new Float32Array(this.texCoords);
        this.indiceBufferData = new Uint16Array(this.indices);
        this.lineIndicesBufferData = new Uint16Array(this.lineIndicesArray)

        // 计算包围盒和包围球
        let box = new Box3();
        let vertexCount = this.positions.length / 3;
        for (let i = 0; i < vertexCount; ++i) {
            let x = this.positions[i * 3];
            let y = this.positions[i * 3 + 1];
            let z = this.positions[i * 3 + 2];
            if (x < box.minx){
                box.minx = x;
            }
            if (x > box.maxx){
                box.maxx = x;
            }
            if (y < box.miny){
                box.miny = y;
            }
            if (y > box.maxy){
                box.maxy = y;
            }
            if (z < box.minz){
                box.minz = z;
            }
            if (z > box.maxz){
                box.maxz = z;
            }
        }
        this.box = box;
        this.radius = Math.max(
            box.maxx - box.minx,
            box.maxy - box.miny,
            box.maxz - box.minz
        ) / 2;

        let bbPositions = [
            box.minx,box.maxy,box.maxz,
            box.maxx,box.maxy,box.maxz,
            box.maxx,box.maxy,box.minz,
            box.minx,box.maxy,box.minz,

            box.minx,box.miny,box.maxz,
            box.maxx,box.miny,box.maxz,
            box.maxx,box.miny,box.minz,
            box.minx,box.miny,box.minz,
        ];
        let bbIndices = [
            0,1,1,2,2,3,3,0,
            4,5,5,6,6,7,7,4,
            0,4,1,5,2,6,3,7,
            1,4,2,5,3,6,4,3,4,6,0,2,
        ];
        this.bbPosBufferData = new Float32Array(bbPositions);
        this.bbIndiceBufferData = new Uint16Array(bbIndices);
    }
}
